package com.peng.herostory.cmdhanlder;

import com.google.protobuf.GeneratedMessageV3;
import com.peng.herostory.util.PackageUtil;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@Slf4j
public final class CmdHandlerFactory {
    private static Map<Class<?>, ICmdHandler<? extends GeneratedMessageV3>> handlerMap = new HashMap<>();

    public static void init() {
        String packageName = CmdHandlerFactory.class.getPackage().getName();
        Set<Class<?>> subClazz = PackageUtil.listSubClazz(packageName, true, ICmdHandler.class);
        for (Class<?> clazz : subClazz) {

            //排除掉接口
            if ((clazz.getModifiers() & Modifier.ABSTRACT) != 0) {
                continue;
            }

            Method[] declaredMethods = clazz.getDeclaredMethods();

            Class<?> msgType = null;
            for (Method declaredMethod : declaredMethods) {
                if (!declaredMethod.getName().equals("handle")) {
                    continue;
                }
                Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
                if (parameterTypes.length < 2 || parameterTypes[1] == GeneratedMessageV3.class
                        || !GeneratedMessageV3.class.isAssignableFrom(parameterTypes[1])) {
                    continue;
                }
                msgType = parameterTypes[1];
                break;
            }
            if (msgType == null) {
                continue;
            }

            try {
                ICmdHandler<?> handler = (ICmdHandler<?>) clazz.newInstance();
                log.info("{}<=>{}", msgType, handler);
                handlerMap.put(msgType, handler);

            } catch (Exception e) {
                log.error("e:{0}", e);
            }
        }
    }

    public static ICmdHandler<? extends GeneratedMessageV3> createHandler(Class<?> msgClazz) {
        if (msgClazz == null) {
            return null;
        }
        return handlerMap.get(msgClazz);
    }

}
